#include "Reactor_Win32.h"

#ifdef SUPPORT_NET

#include "Log.h"

#include <algorithm>
#include <assert.h>

namespace sky
{

    Reactor_Win32::Reactor_Win32()
    {
        // 初始化处理器事件数组
        m_dwArrayCapability = MAXIMUM_WAIT_OBJECTS;
        m_EventHandles = new HANDLE[m_dwArrayCapability];
        memset(m_EventHandles, 0, m_dwArrayCapability * sizeof(HANDLE));

        // 创建处理器自身的事件
        m_hSelfEvent = ::CreateEvent(NULL, FALSE, FALSE, 0);
        // 添加事件监听
        AddEvent(m_hSelfEvent);
        // 给事件组注册理器
        RegisterEventHandlerAux(m_hSelfEvent, this);
    }

    Reactor_Win32::~Reactor_Win32()
    {
        if (m_EventHandles)
        {
            delete[] m_EventHandles;
        }

        if (m_hSelfEvent != INVALID_HANDLE_VALUE)
        {
            ::CloseHandle(m_hSelfEvent);
            m_hSelfEvent = INVALID_HANDLE_VALUE;
        }
    }

    bool Reactor_Win32::AddEvent(HANDLE event)
    {
        REACTOR_TASK task;
        task.event = event;
        task.type = REACTOR_TASK::REACTOR_ADD;
        task.handler = NULL;

        m_TaskLisk.Add(task);
        SetEvent(m_hSelfEvent);

        return true;
    }

    void Reactor_Win32::RemoveEvent(HANDLE event)
    {
        REACTOR_TASK task;
        task.event = event;
        task.type = REACTOR_TASK::REACTOR_DELETE;
        task.handler = NULL;

        m_TaskLisk.Add(task);
        SetEvent(m_hSelfEvent);
    }

    bool Reactor_Win32::RegisterEventHandler(HANDLE event, IEventHandler *handler)
    {
        REACTOR_TASK task;
        task.event = event;
        task.type = REACTOR_TASK::REACTOR_REGISTER;
        task.handler = handler;

        m_TaskLisk.Add(task);
        SetEvent(m_hSelfEvent);

        return true;
    }

    void Reactor_Win32::UnRegisterEventHandler(HANDLE event, IEventHandler *handler)
    {
        REACTOR_TASK task;
        task.event = event;
        task.type = REACTOR_TASK::REACTOR_UNREGISTER;
        task.handler = handler;

        m_TaskLisk.Add(task);
        SetEvent(m_hSelfEvent);
    }

    bool Reactor_Win32::HandleEvents(DWORD wait)
    {
        // 如果事件个数大于64就应该是polling模式,这时候不应该是INFINITE的等待时间
        if (m_dwEventsNum > MAXIMUM_WAIT_OBJECTS)
        {
            if (wait == INFINITE)
            {
                wait = POLLING_INTERVAL;
            }
        }

        // 统一清理已删除的事件
        for(DWORD i = 0; i < m_dwEventsNum; ++i)
        {
            if(m_EventHandles[i] == 0)
            {
                if (i < m_dwEventsNum - 1)
                {
                    memcpy(&m_EventHandles[i], &m_EventHandles[i+1], (m_dwEventsNum-i-1)*sizeof(HANDLE));
                }

                --m_dwEventsNum;
            }
        }

        if (m_dwEventsNum == 0)
        {
            ::Sleep(1);
            return true;
        }

        // 下一轮征询开始的位置
        DWORD offset = 0;
        // 本轮待处理事件
        HANDLE lpHandles[MAXIMUM_WAIT_OBJECTS];
        // 待处理事件在总事件数组的偏移(下标)
        DWORD dwHandlesOffset[MAXIMUM_WAIT_OBJECTS];

        // 开始轮询
        do
        {
            // 取出MAXIMUM_WAIT_OBJECTS个事件处理(WaitForMultipleObjects 最多只能处理MAXIMUM_WAIT_OBJECTS个)
            DWORD dwWaitNum = 0;
            for(; dwWaitNum < MAXIMUM_WAIT_OBJECTS && offset < m_dwEventsNum; ++offset)
            {
                if (m_EventHandles[offset] != 0)
                {
                    lpHandles[dwWaitNum] = m_EventHandles[offset];
                    dwHandlesOffset[dwWaitNum] = offset;
                    ++dwWaitNum;
                }
            }
            
            if(dwWaitNum == 0)
            {
                return true;
            }

            DWORD result = ::WaitForMultipleObjects(dwWaitNum, lpHandles, FALSE, wait);

            // 本来的MAXIMUM_WAIT_OBJECTS个事件 无触发
            if (result == WAIT_TIMEOUT)
            {
                continue;
            }

            if (result == WAIT_FAILED)
            {
                // 这里失败的原因，可能Reactor的线程还在等待，但应用层删除了事件(CloseHandle())，句柄被释放了。待删除后就正常了
                OnEvent(m_hSelfEvent);
                continue;
            }

            DWORD dwIndex = result - WAIT_OBJECT_0;
            if (dwIndex >= 0 && dwIndex < dwWaitNum)
            {
                if (m_hSelfEvent == INVALID_HANDLE_VALUE)
                {
                    return false;
                }

                OnEvent(m_hSelfEvent);

                // 派发给事件处理器
                HANDLER_LIST & handlerList = m_HandlersMap[lpHandles[dwIndex]];
                HANDLER_LIST::iterator it = handlerList.begin();
                for(; it != handlerList.end(); ++it)
                {
                    IEventHandler * handler = *it;
                    handler->OnEvent(lpHandles[dwIndex]);

                    // 只要触发了一轮就一定要设置为POLLING模式，否则后面如果死循环监听就会出问题
                    wait   = POLLING_INTERVAL;

                    // 如果某个事件触发了，则下一轮等待从下一个事件开始，否则如果第一个事件总是触发，则后面的事件就没什么机会被激活了
                    if ( dwIndex<dwWaitNum-1 )
                    {
                        offset = dwHandlesOffset[dwIndex+1];
                    }
                }

                // 如果是第一个事件表示有事件新增或减少,需要重新监听一下
                // 反应器自身事件
                if(dwIndex + offset == 0)
                {
                    return true;
                }

            }
            else
            {
                // 奇怪的返回值
                TraceLn("Reactor_Win32::HandleEvents error" << GetLastError());
                return true;
            }
        } while (offset < m_dwEventsNum);
        

        return true;
    }

    bool Reactor_Win32::HandleEventsLoop()
    {
        // 大于64个事件自动转换为论询模式
        while( HandleEvents(m_dwEventsNum > MAXIMUM_WAIT_OBJECTS ? POLLING_INTERVAL : INFINITE) && m_bRun)
        {

        }

        // 线程退出后，补发一次事件给其他线程
        notifyStop();

        return true;
    }

    void Reactor_Win32::notifyStop()
    {
        m_bRun = false;
        if (m_EventHandles && m_dwEventsNum > 0)
        {
            SetEvent(m_EventHandles[m_dwEventsNum - 1]);
        }

        if (m_hSelfEvent)
        {
            SetEvent(m_hSelfEvent);
        }
    }

    void Reactor_Win32::NotifyExit()
    {
        REACTOR_TASK task;
        task.event = 0;
        task.type = REACTOR_TASK::REACTOR_EXIT;
        task.handler = NULL;

        m_TaskLisk.Add(task);
        SetEvent(m_hSelfEvent);
    }

    void Reactor_Win32::Release()
    {
        delete this;
    }

    void Reactor_Win32::OnEvent(HANDLE event)
    {
        if (event == INVALID_HANDLE_VALUE)
        {
            return;
        }

        REACTOR_TASK task;
        while(m_TaskLisk.Get(task))
        {
            switch (task.type)
            {
            case REACTOR_TASK::REACTOR_ADD :
                AddEventAux(task.event);
                break;
            case REACTOR_TASK::REACTOR_DELETE :
                RemoveEventAux(task.event);
                break;
            case REACTOR_TASK::REACTOR_REGISTER :
                RegisterEventHandlerAux(task.event, task.handler);
                break;
            case REACTOR_TASK::REACTOR_UNREGISTER :
                UnRegisterEventHandlerAux(task.event, task.handler);
                break;
            case REACTOR_TASK::REACTOR_EXIT :
                NotifyExitAux();
                break;
            default:
                assert(false);
                break;
            }
        }
    }

    bool Reactor_Win32::AddEventAux(HANDLE event)
    {
        if (m_dwEventsNum >= m_dwArrayCapability)
        {
            // 扩容
            m_dwArrayCapability += MAXIMUM_WAIT_OBJECTS;
            HANDLE * newArray = new HANDLE[m_dwArrayCapability];
            memccpy(newArray, m_EventHandles, m_dwEventsNum * sizeof(HANDLE));
            delete[] m_EventHandles;
            m_EventHandles = newArray;
        }

        for(DWORD i = 0; i < m_dwEventsNum; ++i)
        {
            if (m_EventHandles[i] == event)
            {
                return false;
            }
        }

        m_EventHandles[m_dwEventsNum] = event;
        m_dwEventsNum ++;

        return true;
    }

    void Reactor_Win32::RemoveEventAux(HANDLE event)
    {
        for (DWORD i = 0; i < m_dwEventsNum; ++i)
        {
            if (m_EventHandles[i] == event)
            {
                //不要真正删除,先做个标记，否则位置变来变去容易出错
                m_EventHandles[i] = 0;
            }
        }

        m_HandlersMap.erase(event);
    }

    bool Reactor_Win32::RegisterEventHandlerAux(HANDLE event, IEventHandler *handler)
    {

        HANDLER_LIST & handlerList = m_HandlersMap[event];
        HANDLER_LIST::iterator it = std::find(handlerList.begin(), handlerList.end(), handler);
        if (it != handlerList.end())
        {
            return;
        }

        handlerList.push_back(handler);

        return true;
    }

    void Reactor_Win32::UnRegisterEventHandlerAux(HANDLE event, IEventHandler *handler)
    {
        HANDLER_LIST & handlerList = m_HandlersMap[event];
        HANDLER_LIST::iterator it = std::find(handlerList.begin(), handlerList.end(), handler);
        if (it != handlerList.end())
        {
            handlerList.erase(it);
        }
    }

    void Reactor_Win32::NotifyExitAux()
    {
        ::ExitThread(0);
    }

} // namespace sky

#endif // SUPPORT_NET